NO.17 电话号码的字母组合 中等
思路一:回溯法 如果这道题加一个条件:“每次输入3位字符的字符串”。那么这道题就非常简单了,直接三层for循环就解决了。这道题棘手的地方就是如何确定循环的层数,这时候递归就派上用场了(模仿大佬的语气)!
例如输入”2345”这样的字符串:第一次递归处理2,然后处理完第一个字符2之后,将输入的字符改变成”345”并调用第二个递归函数;第二次递归处理3,将字符串改变成”45”后再次递归;第三次递归处理4,将字符串改变成 “5”后继续递归;第四次递归处理5,将字符串改变成””后继续递归;最后发现字符串为空了,将结果放到列表中并返回。
上面是从函数调用的角度去看的,而每次调用下一层递归时,都需要将本层的一些处理结果放到一个临时变量中,再传递给下一层,从这个变量层层传递的变化看,就像一棵树一样,这个算法的时间复杂度很高,是O(3^n)这个级别的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| String[] letters={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
List<String> result=new ArrayList<>();
public List<String> letterCombinations(String digits) {
if (digits.length()==0||digits==null)return result; backTrack(digits,"",0); return result; }
public void backTrack(String str,String combination,int index){
if (index==str.length()){ result.add(combination); return; }
char c= str.charAt(index); String letter=letters[c-'0'];
for (int i=0;i<letter.length();i++){
backTrack(str,combination+letter.charAt(i),index+1); } }
|
时间复杂度:O(3^n)
思路二:队列法 利用队列先进先出的特点来处理该问题。
直接用一个例子来说明思路:假设输入的还是”23”,先将”2”对应的字符依次放入队列,队列res变为{“a”,”b”,”c”};将此时队列中的每个字符串依次取出的同时分别和下一个输入数字所对应的字符拼接后重新放入队列,将”a”取出和第二个输入数字”3”对应的字符”def”依次拼接后重新放入队列,队列res变为{“b”,”c”,”ad”,”ae”,”af”},将”b”取出和第二个输入数字”3”对应的字符”def”依次拼接后重新放入队列,队列res变为{“c”,”ad”,”ae”,”af”,”bd”,”be”,”bf”},将”c”取出和第二个输入数字”3”对应的字符”def”依次拼接后重新放入队列,队列res变为{“ad”,”ae”,”af”,”bd”,”be”,”bf”,”cd”,”ce”,”cf”};所有输入数字遍历结束。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public List<String> letterCombinations(String digits) { List<String> res=new ArrayList<>();
if (digits==null||digits.length()==0)return res;
String[] letters={"","#","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
res.add("");
for(int i=0;i<digits.length();i++){
String letter=letters[digits.charAt(i)-'0'];
int size = res.size();
for (int j=0;j<size;j++){
String temp = res.remove(0);
for (int k=0;k<letter.length();k++){ res.add(temp+letter.charAt(k)); } } } return res; }
|
时间复杂度:O(3^n)
本人菜鸟,有错误请告知,感激不尽!
更多题解和学习记录博客:博客、github